package models

import (
	"gitee.com/kudingc/role_proxy/common"
	"github.com/astaxie/beego/orm"
	"net"
	"strconv"
)

// 微服务

type MicroState int // 微服务在线状态

// 审批流是否已读
const (
	// Offline 离线
	Offline MicroState = iota
	// Online 在线
	Online
)

var (
	RegisteredMicroservice      = make(map[string]map[string]SysRegService) // 已注册微服务列表 第一个key为微服务code,第二个key为微服务副本num
	ConnRegMicro                = make(map[string]SysRegService)            // 连接对象与已注册微服务对照表，key为客户端addr，value为微服务code
	RegisteredMicroserviceQueue = make(map[string]*Queue)                   // 已注册微服务堆栈列表 key为微服务code，value为code对应的不同副本num组成的堆栈，该堆栈为先进先出
)

// MicroService 微服务结构体
type MicroService struct {
	Id          int    `json:"id"`           // 微服务id
	Code        string `json:"code"`         // 微服务code
	CopyNum     string `json:"copy_num"`     // 副本编号，默认为0。预留，目前设计一个微服务只有一个副本，有多个副本的情况还要设置负载均衡，后面再扩展
	ServiceAddr string `json:"service_addr"` // 微服务ip及端口
	Note        string `json:"note"`         // 微服务说明
}

// MicroserviceClear 清空服务器中的微服务注册信息
func MicroserviceClear() (err error) {
	sql := "delete from sys_reg_service;"
	common.Db.Raw(sql).Exec()
	return
}

// RegisterMicroservice 注册微服务
func (u *MicroService) RegisterMicroservice(conn net.Conn) (err error) {
	var sysRegService SysRegService
	var maps []orm.Params

	// 检查当前微服务信息已在数据库中
	sql := "select * from sys_reg_service where micro_id = ? and code = ? and copy_num = ? and service_addr = ?"
	_, err = common.Db.Raw(sql, u.Id, u.Code, u.CopyNum, u.ServiceAddr).Values(&maps)
	if err != nil {
		return
	}
	sysRegService = SysRegService{
		MicroId:     u.Id,
		Code:        u.Code,
		CopyNum:     u.CopyNum,
		ServiceAddr: u.ServiceAddr,
		Note:        u.Note,
		State:       Online,
	}
	if len(maps) == 0 {
		// 插入
		_, err = common.Db.Insert(&sysRegService)
	} else {
		// 更新
		sysRegService.Id, _ = strconv.Atoi(maps[0]["id"].(string))
		_, err = common.Db.Update(&sysRegService, "note", "state")
	}
	if err != nil {
		return
	}

	ConnRegMicro[conn.RemoteAddr().String()] = sysRegService
	if _, ok := RegisteredMicroservice[u.Code]; !ok {
		RegisteredMicroservice[u.Code] = make(map[string]SysRegService)
	}
	RegisteredMicroservice[u.Code][u.CopyNum] = sysRegService

	if _, ok := RegisteredMicroserviceQueue[u.Code]; ok {
		RegisteredMicroserviceQueue[u.Code].EnQueue(sysRegService)
	} else {
		queue := NewQueue()
		queue.EnQueue(sysRegService)
		RegisteredMicroserviceQueue[u.Code] = &queue
	}
	return
}

// UnRegisterMicroservice 取消注册微服务
func (u *MicroService) UnRegisterMicroservice(conn net.Conn) {
	sysRegService := ConnRegMicro[conn.RemoteAddr().String()]
	if sysRegService.Id == 0 {
		return
	}
	sysRegService.State = Offline
	ConnRegMicro[conn.RemoteAddr().String()] = sysRegService
	RegisteredMicroservice[sysRegService.Code][sysRegService.CopyNum] = sysRegService
	common.Db.Update(&sysRegService, "state")
	return
}
